package biz

import (
	"context"
	"github.com/go-kratos/kratos/v2/log"
	"golang.org/x/crypto/bcrypt"
	"kratos-realworld/internal/conf"
	"kratos-realworld/internal/pkg/middleware"
)

type User struct {
	Email        string
	Username     string
	bio          string
	image        string
	PasswordHash string
}

type UserLogin struct {
	Email    string
	Token    string
	Username string
	bio      string
	image    string
}

type UserRepo interface {
	CreateUser(ctx context.Context, user *User) error
	GetUserByEmail(ctx context.Context, email string) (*User, error)
}

type ProfileRepo interface {
}

type UserUsecase struct {
	user    UserRepo
	profile ProfileRepo

	log  *log.Helper
	jwtc *conf.JWT
}

func NewUserUsecase(user UserRepo, profile ProfileRepo, logger log.Logger, jwtc *conf.JWT) *UserUsecase {
	return &UserUsecase{
		user:    user,
		profile: profile,
		log:     log.NewHelper(logger),
		jwtc:    jwtc,
	}
}

func (uc *UserUsecase) generateToken(username string) string {
	return middleware.GenerateToken(uc.jwtc.Secret, username)
}

func (uc *UserUsecase) Register(ctx context.Context, email, username, password string) (*UserLogin, error) {
	user := &User{
		Email:        email,
		Username:     username,
		PasswordHash: hashPassword(password),
		bio:          "",
		image:        "",
	}
	if err := uc.user.CreateUser(ctx, user); err != nil {
		uc.log.Errorf("register user failed: %v", err)
		return nil, err
	}
	return &UserLogin{
		Email:    user.Email,
		Username: user.Username,
		bio:      user.bio,
		image:    user.image,
		Token:    uc.generateToken(user.Username),
	}, nil
}

func (uc *UserUsecase) Login(ctx context.Context, email string, password string) (*UserLogin, error) {
	user, err := uc.user.GetUserByEmail(ctx, email)
	if err != nil {
		uc.log.Errorf("login user failed: %v", err)
		return nil, err
	}
	if err := verifyPassword(password, user.PasswordHash); err != nil {
		uc.log.Errorf("login user failed: %v", err)
		return nil, err
	}
	return &UserLogin{
		Email:    user.Email,
		Username: user.Username,
		bio:      user.bio,
		image:    user.image,
		Token:    uc.generateToken(user.Username),
	}, nil
}

func hashPassword(password string) string {
	b, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	return string(b)
}

func verifyPassword(password, hash string) error {
	return bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
}
